package com.xyzwps.mvckotlin.handler.helper

import com.xyzwps.mvckotlin.exception.unhandled
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.reactive.awaitSingle
import kotlinx.coroutines.reactor.mono
import kotlinx.coroutines.slf4j.MDCContext
import org.springframework.web.reactive.function.server.*
import org.springframework.web.reactive.function.server.RequestPredicates.path

fun <T : ServerResponse> nest(pathString: String, routerFunction: RouterFunction<T>): RouterFunction<T>
    = RouterFunctions.nest(path(pathString), routerFunction)

fun routes(predicate: RequestPredicate, handler: RequestHandler) = RouterFunctions.route(predicate, HandlerFunction { handler(it) })

internal fun RouterFunction<ServerResponse>.filterWrapper(handler: suspend (ServerRequest) -> Unit) = this.filter { req, next ->
    mdc(req)
    GlobalScope.mono(MDCContext()) {
        handler(req)
        return@mono req // 硬发送一个对象到下游
    }.flatMap {
        next.handle(req)
    }.onErrorResume {
        // TODO: handler 发生错误时，如何指导错误处理？handler 的抽象程度应该不够
        ServerResponse.ok().render("redirect:/home")
    }
}

fun RouterFunction<ServerResponse>.auth(): RouterFunction<ServerResponse> = this.filterWrapper {
    val session = it.session().awaitSingle()
    val userInfo = session.getUserInfo()
    userInfo ?: throw unhandled()
}

fun RouterFunction<ServerResponse>.andNest(pathString: String, routerFunction: RouterFunction<ServerResponse>)
    = this.andNest(path(pathString), routerFunction)
